//Author: Max Charnock
//Date: 10/02/2015
//Purpose: Manages HUD entities and sends them to the renderer to Draw
//Singleton Classs

#pragma once

#include "FPSCounter.h"
#include "Button.h"
#include "../../nclgl/ControllerHeader.h"
#include "XBOXController.h"
#include "GameSound.h"
#include "SpringNet.h"
#define INTIALTIME 40.0f
#define INTIALSCORE 0.0f

//possible HUD states
enum HUDSTATES { MAIN, PAUSED, GAME, GAMEOVER };

//struct used for high scores
struct HighScorePoints
{
public:

	string Name;

	int Score;
};


class HUDManager
{
protected:

	HUDManager();
	~HUDManager(); 

	// ---------- Added by Monica ----------- //
	bool SinglePlayer;
	bool MultiPlayer;
	// ------------------------------------ //

	/*pointer to HUDmanager instance*/
	static HUDManager* pInst;

	FpsCounter Render_Counter;
	FpsCounter Physics_Counter;

	//bool used to determine debug display, controls FPS counters
	bool Debug_Mode;

	//bool used to determine whether to exit the programme
	bool Exit;

	//bool used to determine whether to restart the programme
	bool Restart;

	//bool used to determine which display state to put the game in
	bool Fullscreen;

	//how long the player has left before game session is over
	float GameTime;

	//the players score
	float Score;

	//player health reference
	int Player_Health;
	//player energy reference
	float player_energy;
	//vectors of buttons used in variose HUd states
	vector<Button<HUDManager>*> PauseButtons;
	vector<Button<HUDManager>*> StartButtons;
	vector<Button<HUDManager>*> GameOverButtons;

	//current selected button for menu navigation
	vector<Button<HUDManager>*>::iterator Selected_Button;

	//vurrent list selected button is navigating
	vector<Button<HUDManager>*>* ActiveList;

	//high score array
	HighScorePoints High_Score[10];

	//logo in main menu
	SceneNode Logo;

	//health bar in main game
	SceneNode Health_Bar;

	//energy bar in main game
	SceneNode Energy_bar;

	//xbox controller
	XBOXController* playerXbox_controller;

	//current state of the HUD
	HUDSTATES HUDState;

	bool deathDelay;
	float deathTime;
public:

	//Gets/Created HUDManager instance
	static HUDManager* GetInstance();

	//Releases HUDManager Instance
	void Release();

	// Creates Hud buttons and other elements
	void Intialise();

	//checks for key pressed and updates timers
	void Update(float msec);

	//loads current high scores from text file
	void LoadHighScore(char* filename);

	//writes high scores to text file
	void WriteHighScore(char* filename);

	//compares an int against high scores and if higher than a value adds it so high score
	void AddScore(string name ,int score);

	//moves button iterator up
	void MoveMenuUp();
	//move button iterator down
	void MoveMenuDown();

	//returns current state of the HUD
	HUDSTATES GetHUDState() { return HUDState; }

	//updates FPS counters
	void UpdateRenderFPS(float msec)	{Render_Counter.Update(msec);}
	int GetRenderFPS()					{return Render_Counter.GetFPS();}
	void UpdatePhysicsFPS(float msec)	{Physics_Counter.Update(msec);}
	int GetPhysicsFPS()					{return Physics_Counter.GetFPS();}

	//toggle and get function for debug bool
	void ToggleDebugMode() { Debug_Mode = !Debug_Mode;}
	bool GetDebugMode() {return Debug_Mode;}

	//toggle and get function for exit bool
	void ToggleExit() { Exit = !Exit;}
	bool GetExit() {return Exit;}

	// -------- Added by Monica ------- //
	void SetMultiPlayer() { MultiPlayer = true; SwitchToGame(); }
	void SetSinglePlayer() { SinglePlayer = true; SwitchToGame(); }

	bool GetMultiPlayer() const { return MultiPlayer; }
	bool GetSinglePlayer() const { return SinglePlayer; }
	// ---------------------------------- //

	//toggle and get function for reset bool
	void ToggleReset_HUD() { Restart = !Restart; }
	bool GetReset_HUD() {return Restart;}

	//return game time 
	float GetGameTime(){return GameTime;}

	//get the energy_bar
	SceneNode* getEnergyBar(){ return &Energy_bar; }
	//sets player energy for HUD, wanted to use a pointer but got linker issues
	void SetPlayerEnergy(int player){ player_energy = player; }

	//get and update for score
	float GetScore(){ return Score; }
	void UpdateScore(float scoreadd){ Score += scoreadd; }

	//sets controller pointer
	void SetPlayerXboxController(XBOXController* controller){ playerXbox_controller = controller; }

	//resets the HUD
	void Reset();

	//sets player health for HUD, wanted to use a pointer but got linker issues
	void SetPlayerHealth(int player){Player_Health = player;}

	//returns list of HUD elements that need to drawn, this is dependant on the state of the HUD
	vector<SceneNode*> GetDrawList();

	//returns the high score list
	vector<string> GetHighScoreText();

	//funtions for switching between HUD states
	void SwitchToGame();
    void SwitchToMain();
    void SwitchToPaused();
	void SwitchToGameOver();
	
	//toggles fullscreem on and off
	void ToggleFullscreen()
	{
		Fullscreen = !Fullscreen;

		if(Fullscreen)
		{
			SetWindowLongPtr(Window::GetWindow().GetHandle(), GWL_STYLE, 
			WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
			MoveWindow(Window::GetWindow().GetHandle(), 0, 0, 1280, 800, TRUE);

			DEVMODE dmScreenSettings;								// Device Mode
			memset(&dmScreenSettings,0,sizeof(dmScreenSettings));	// Makes Sure Memory's Cleared

			dmScreenSettings.dmSize=sizeof(dmScreenSettings);		// Size Of The Devmode Structure
			dmScreenSettings.dmPelsWidth	= 1280;				// Selected Screen Width
			dmScreenSettings.dmPelsHeight	= 800;				// Selected Screen Height
			dmScreenSettings.dmBitsPerPel	= 32;					// Selected Bits Per Pixel
			dmScreenSettings.dmDisplayFrequency = 60;
			dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;

			ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN);
		}
		else
		{
			RECT rect;
			rect.left = 0;
			rect.top = 0;
			rect.right = 1280;
			rect.bottom = 800;

			ChangeDisplaySettings(0, 0);

			SetWindowLongPtr(Window::GetWindow().GetHandle(), GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
			AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
			MoveWindow(Window::GetWindow().GetHandle(), 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
		}

	}

	void AddTime(){ GameTime += 10.0f;}
};